package cn.com.libertymutual.sp.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import cn.com.libertymutual.core.banks.CheckBankCard;
import cn.com.libertymutual.core.base.dto.PrpLmAgent;
import cn.com.libertymutual.core.base.dto.TQueryLmAgentResponseDto;
import cn.com.libertymutual.core.http.HttpAndHttpsUtil;
import cn.com.libertymutual.core.http.HttpUtilsAlibaba;
import cn.com.libertymutual.core.redis.util.RedisUtils;
import cn.com.libertymutual.core.security.encoder.Md5PwdEncoder;
import cn.com.libertymutual.core.util.BeanUtilExt;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.Current;
import cn.com.libertymutual.core.util.DateUtil;
import cn.com.libertymutual.core.util.ImgMainColor;
import cn.com.libertymutual.core.util.PinYinUtils;
import cn.com.libertymutual.core.util.StringUtil;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.bean.TbSpAgreementNoConfig;
import cn.com.libertymutual.sp.bean.TbSpApprove;
import cn.com.libertymutual.sp.bean.TbSpBank;
import cn.com.libertymutual.sp.bean.TbSpBankCard;
import cn.com.libertymutual.sp.bean.TbSpFlow;
import cn.com.libertymutual.sp.bean.TbSpFlowDetail;
import cn.com.libertymutual.sp.bean.TbSpSaleLog;
import cn.com.libertymutual.sp.bean.TbSpScore;
import cn.com.libertymutual.sp.bean.TbSpStoreConfig;
import cn.com.libertymutual.sp.bean.TbSpUser;
import cn.com.libertymutual.sp.bean.TbSysHotarea;
import cn.com.libertymutual.sp.biz.IdentifierMarkBiz;
import cn.com.libertymutual.sp.dao.AgreementNoConfigDao;
import cn.com.libertymutual.sp.dao.ApproveDao;
import cn.com.libertymutual.sp.dao.BankDao;
import cn.com.libertymutual.sp.dao.CashLogDao;
import cn.com.libertymutual.sp.dao.DrawLogDao;
import cn.com.libertymutual.sp.dao.FlowDao;
import cn.com.libertymutual.sp.dao.FlowDetailDao;
import cn.com.libertymutual.sp.dao.ManualDetailDao;
import cn.com.libertymutual.sp.dao.ProductDao;
import cn.com.libertymutual.sp.dao.ScoreDao;
import cn.com.libertymutual.sp.dao.ScoreLogInDao;
import cn.com.libertymutual.sp.dao.ScoreLogOutDao;
import cn.com.libertymutual.sp.dao.SpSaleLogDao;
import cn.com.libertymutual.sp.dao.StoreConfigDao;
import cn.com.libertymutual.sp.dao.TbSysHotareaDao;
import cn.com.libertymutual.sp.dao.UserDao;
import cn.com.libertymutual.sp.dto.UserDto;
import cn.com.libertymutual.sp.req.StoreRateReq;
import cn.com.libertymutual.sp.service.api.ActivityService;
import cn.com.libertymutual.sp.service.api.AdminService;
import cn.com.libertymutual.sp.service.api.BankCardService;
import cn.com.libertymutual.sp.service.api.BaseService;
import cn.com.libertymutual.sp.service.api.ShopService;
import cn.com.libertymutual.sp.service.api.SmsService;
import cn.com.libertymutual.sp.service.api.UserService;
import cn.com.libertymutual.sys.bean.SysServiceInfo;
import cn.com.libertymutual.sys.bean.SysUser;
import cn.com.libertymutual.sys.dao.ISysRoleUserDao;
import cn.com.libertymutual.sys.dao.ISysServiceInfoDao;
import cn.com.libertymutual.sys.dao.ISysUserDao;
import cn.com.libertymutual.sys.service.api.ISequenceService;
import cn.com.libertymutual.wx.common.MessageType;
import cn.com.libertymutual.wx.message.WeChatUser;
import cn.com.libertymutual.wx.service.WeChatService;

@Service("UserService")
@RefreshScope // 刷新配置无需重启服务
public class UserServiceImpl implements UserService {

	/** 获取和存储默认银行卡图标相对路径 */
	@Value("${file.transfer.bankImgPathDefault}")
	private String bankImgPathDefault;

	/** 获取和存储默认头像相对路径 */
	@Value("${file.transfer.userHeadImgPathDefault}")
	private String userHeadImgPathDefault;

	/** 默认头像图片名称 */
	@Value("${file.transfer.headImgDefault}")
	private String headImgDefault;

	private Logger log = LoggerFactory.getLogger(getClass());
	@Autowired
	private UserDao userDao;
	@Autowired
	private ProductDao productDao;
	@Autowired
	private ApproveDao approveDao;
	@Autowired
	private BankDao bankDao;
	@Autowired
	private StoreConfigDao storeConfigDao;
	@Autowired
	private AgreementNoConfigDao agreementNoConfigDao;
	@Autowired
	private ISysServiceInfoDao iSysServiceInfoDao;
	@Autowired
	private SpSaleLogDao spSaleLogDao;
	@Autowired
	private ISysUserDao iSysUserDao;
	@Autowired
	private ISysRoleUserDao roleUserDao;
	@Autowired
	private FlowDao flowDao;
	@Autowired
	private FlowDetailDao flowDetailDao;
	@Resource
	private ScoreDao scoreDao;
	@Resource
	private CashLogDao cashLogDao;
	@Resource
	private DrawLogDao drawLogDao;
	@Resource
	private ManualDetailDao manualDetailDao;
	@Resource
	private ScoreLogInDao scoreLogInDao;
	@Resource
	private ScoreLogOutDao scoreLogOutDao;

	@Autowired
	private ActivityService activityService;
	@Autowired
	private ISequenceService iSequenceService;
	@Autowired
	private SmsService smsService;
	@Resource
	private WeChatService weChatService;
	@Resource
	private BaseService baseService;
	@Autowired
	private BankCardService cardService;
	@Autowired
	private TbSysHotareaDao hotareaDao;
	@Resource
	private ShopService shopService;
	@Autowired
	private AdminService adminService;
	@Resource
	private IdentifierMarkBiz identifierMarkBiz;
	@Resource
	private RedisUtils redis;

	public static void main(String[] args) {
		String host = "http://ali-bankcard.showapi.com";
		String path = "/bankcard";
		String method = "GET";
		String appcode = "你自己的AppCode";
		HashMap<String, String> headers = new HashMap<String, String>();
		// 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
		headers.put("Authorization", "APPCODE " + appcode);
		HashMap<String, String> querys = new HashMap<String, String>();
		querys.put("kahao", "6215982582010042122");

		try {
			/**
			 * 重要提示如下: HttpUtils请从
			 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
			 * 下载
			 *
			 * 相应的依赖请参照
			 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
			 */
			HttpResponse response = HttpUtilsAlibaba.doGet(host, path, method, headers, querys);
			System.out.println("======+===>" + response.toString());
			// 获取response的body
			System.out.println("=========>" + EntityUtils.toString(response.getEntity()));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Remarks: 创建个人用户(synchronized同步线程方式)<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年11月14日上午10:40:59<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param userDto
	 * @param weChatUser
	 * @return TbSpUser
	 * @throws Exception
	 */
	public synchronized TbSpUser createUser(UserDto userDto, WeChatUser weChatUser) throws Exception {
		Timestamp timestamp = new Timestamp(new Date().getTime());

		TbSpUser user = new TbSpUser();
		user.setRefereeId(userDto.getRefereeId());
		user.setRefereePro(userDto.getRefereePro());
		user.setRegisteDate(timestamp);// 注册时间
		user.setLastloginDate(timestamp);// 最后登录时间
		user.setLoginTimes(1);

		// 微信
		if (null != weChatUser && StringUtils.isNotBlank(weChatUser.getOpenid())) {
			// 映射属性
			weChatService.copyWeChatToBbean(weChatUser, user, false);
			// 设置序列号
			user.setUserCode(iSequenceService.getUserCodeSequence("WX"));
		} else {
			// 普通注册
			user.setUserCode(iSequenceService.getUserCodeSequence("BS"));
			if (StringUtils.isNotBlank(userDto.getEmployeeCode())) {
				user.setEmployeeCode(userDto.getEmployeeCode());
			}
			if (StringUtils.isNotBlank(userDto.getNickName())) {
				user.setNickName(userDto.getNickName());
			}
			if (StringUtils.isNotBlank(userDto.getMobile())) {
				user.setMobile(userDto.getMobile());
			}
			user.setHeadUrl(this.userHeadImgPathDefault + this.headImgDefault);
		}
		user = userDao.save(user);

		return user;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public synchronized TbSpUser createFrontChannelUser(UserDto userDto) throws Exception {

		Timestamp timestamp = new Timestamp(new Date().getTime());

		TbSpUser user = new TbSpUser();
		user.setUserCode(iSequenceService.getUserCodeSequence("BS"));

		user.setRegisteDate(timestamp);// 注册时间
		user.setLastloginDate(timestamp);// 最后登录时间
		user.setLoginTimes(1);

		user.setUpUserCode(userDto.getUpUserCode());
		user.setEmployeeCode(userDto.getEmployeeCode());// 员工编码
		user.setUserName(userDto.getUserName());// 姓名
		user.setNickName(userDto.getNickName());// 昵称

		String password = userDto.getPassword();
		if (StringUtils.isNotBlank(password)) {
			// 加密密码
			password = new Md5PwdEncoder().encodePassword(password);
			user.setPassword(password);// 密码
		}

		user.setMobile(userDto.getMobile());// 手机号
		user.setIdNumber(userDto.getIdNumber());// 证件号
		user.setIdType(userDto.getIdType());// 证件类型
		user.setCanModify(userDto.getCanModify());
		user.setCanScore(userDto.getCanScore());
		user.setBaseRate(userDto.getBaseRate());
		user.setStoreFlag("1");
		user.setStoreCreateTime(timestamp);

		String redisBranch = userDto.getBranchCode();// 机构编码
		if (StringUtils.isNotBlank(redisBranch) && redisBranch.length() >= 4) {
			redisBranch = redisBranch.substring(0, 4);
		}
		// 用户类型
		String userType = "2";// 默认普通账户 // 已废弃：this.getUserType(orgCode, licenceNo, accType, codeType);

		if (StringUtils.isNotBlank(userDto.getAgrementNo())) {
			// 有代理人代码和名称的算中介协议，余下的算CA协议
			if (StringUtils.isNotBlank(userDto.getAgrementName())) {
				userType = "3";// 专业代理
			} else {
				// CA协议
				if (StringUtils.isNotBlank(userDto.getOrgCode()) || StringUtils.isNotBlank(userDto.getLicenceNo())) {
					userType = "4";// 商户
				} else {
					userType = "5";// 销售人员
				}
			}
		}
		user.setUserType(userType);
		user.setRegisterType(userDto.getRegisterType());// 注册类型

		user.setComCode(userDto.getComCode());// 所属部门-上级编码

		user.setShopName(userDto.getShopName());// 渠道名称作为店铺名称
		user.setBranchCode(redisBranch);// 业务关系代码所属机构编码
		user.setAgrementNo(userDto.getAgrementNo());// 业务关系代码
		user.setAgrementName(userDto.getAgrementName());// 代理名称
		user.setSaleCode(userDto.getSaleCode());// 销售人员编码
		user.setSaleName(userDto.getSaleName());// 销售人员名称
		user.setChannelType(userDto.getCustomerType());// 客户单位类型
		user.setCustomName(userDto.getCustomerName());// 客户单位名称

		user.setChannelCode(userDto.getChannelCode());// 业务关系代码渠道编码
		user.setChannelName(userDto.getChannelName());// 渠道名称

		user.setAreaCode(userDto.getAreaCode());
		user.setAreaName(userDto.getAreaName());

		user.setHeadUrl(this.userHeadImgPathDefault + this.headImgDefault);
		try {
			user = userDao.save(user);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		// 存储分享信息
		shopService.saveShare(user.getUserCode(), "渠道-自动生成", ":1");

		return user;
	}

	@Override
	public synchronized ServiceResult createSysChannelUser(UserDto userDto, TbSpUser spUser) throws Exception {
		ServiceResult sr = new ServiceResult("创建后台账户失败", ServiceResult.STATE_APP_EXCEPTION);
		SysUser sysUser = null;

		List<SysUser> dbsysuser = iSysUserDao.findByMobile(userDto.getMobile());

		if (CollectionUtils.isNotEmpty(dbsysuser) && StringUtils.isNotBlank(userDto.getIsMergeUser())
				&& Constants.TRUE.equals(userDto.getIsMergeUser())) {

			sysUser = dbsysuser.get(0);
			roleUserDao.updateRole(9, sysUser.getUserid());// 改为渠道角色

			sysUser.setUserid(spUser.getUserCode());

			if (StringUtils.isNotBlank(userDto.getType()) && StringUtils.isNotBlank(userDto.getUserName())
					&& Constants.FALSE.equals(userDto.getType())) {

				SysUser dbSysUser = iSysUserDao.findByUserid(userDto.getUserName());
				if (null != dbSysUser) {// 已存在的后台操作用户,改为渠道角色
					sysUser.setType(userDto.getType());
					spUser.setUserCode(userDto.getUserName());

					roleUserDao.updateRole(9, dbSysUser.getUserid());
				}
			}

		} else {// 新建后台用户
			if (StringUtils.isNotBlank(userDto.getType()) && StringUtils.isNotBlank(userDto.getUserName())
					&& Constants.FALSE.equals(userDto.getType())) {
				SysUser dbSysUser = iSysUserDao.findByUserid(userDto.getUserName());
				if (null != dbSysUser) {// 已存在的后台操作用户,改为渠道角色
					roleUserDao.updateRole(9, dbSysUser.getUserid());
				} else {
					// 内部用户校验
					sr = adminService.getUserInfoFromLdap(userDto.getUserName());
					if (sr.getState() != 0) {
						return sr;
					}
					sysUser = new SysUser();
					sysUser.setLoginnum(0);
					sysUser.setStatus("1");
					sysUser.setType(userDto.getType());
					sysUser.setCreated(Current.date.get());
					sysUser.setCreater(Current.userId.get());
					sysUser.setUserid(userDto.getUserName());
					sysUser.setUsername(userDto.getUserName());
					sysUser.setPassword(userDto.getPassword());
				}
			} else {
				sysUser = new SysUser();
				sysUser.setLoginnum(0);
				sysUser.setStatus("1");
				sysUser.setType(userDto.getType());
				sysUser.setCreated(Current.date.get());
				sysUser.setCreater(Current.userId.get());
				sysUser.setUserid(spUser.getUserCode());
				sysUser.setUsername(spUser.getUserCode());
				sysUser.setPassword(userDto.getPassword());
			}
		}

		if (sysUser != null) {
			// 更新或新增
			iSysUserDao.save(sysUser);
		}

		sr.setSuccess();
		sr.setResult(sysUser);
		return sr;
	}

	@Override
	public ServiceResult register(HttpServletRequest request, ServiceResult sr, UserDto userDto) throws Exception {
		sr.setAppFail("注册失败");
		if (StringUtils.isBlank(userDto.getNickName())) {
			sr.setResult("请输入用户名");
			return sr;
		}
		if (userDto.getNickName().length() < 3 || userDto.getNickName().length() > 20) {
			sr.setResult("用户名长度为3-20位");
			return sr;
		}
		List<TbSpUser> oldUsers = userDao.findByMobile(userDto.getMobile());
		if (CollectionUtils.isNotEmpty(oldUsers) || oldUsers.size() > 0) {
			sr.setResult("手机号[" + userDto.getMobile().substring(0, 3) + "*****"
					+ userDto.getMobile().substring(userDto.getMobile().length() - 3, userDto.getMobile().length()) + "]已被使用");
			return sr;
		}

		sr.setResult(this.createUser(userDto, null));
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult registerChannel(HttpServletRequest request, ServiceResult sr, UserDto userDto, String type) throws Exception {
		sr.setAppFail("注册失败");

		if (StringUtils.isBlank(userDto.getComCode())) {
			sr.setResult("受邀信息错误");
			return sr;
		}

		// 查询上级渠道是否存在
		TbSpUser superUser = userDao.findByUserCode(userDto.getComCode());
		if (superUser == null) {
			sr.setResult("邀请人不存在");
			return sr;
		}

		if (StringUtils.isBlank(userDto.getEmployeeCode())) {
			sr.setResult("请输入员工编码");
			return sr;
		}
		if (StringUtils.isBlank(userDto.getUserName())) {
			sr.setResult("请输入姓名");
			return sr;
		}
		if (userDto.getUserName().length() < 2) {
			sr.setResult("姓名至少2个字符");
			return sr;
		}
		if (userDto.getUserName().length() > 50) {
			sr.setResult("姓名最多50个字符");
			return sr;
		}
		if (!StringUtil.isAllChinese(userDto.getUserName())) {
			sr.setResult("真实姓名只能是中文");
			return sr;
		}
		// 昵称默认为姓名
		userDto.setNickName(userDto.getUserName());

		if (StringUtils.isBlank(userDto.getIdNumber())) {
			sr.setResult("请输入身份证号码");
			return sr;
		}
		if (userDto.getIdNumber().trim().length() < 15 || userDto.getIdNumber().trim().length() > 18) {
			sr.setResult("证件号码长度为15-18个字符");
			return sr;
		}
		// if (StringUtils.isBlank(userDto.getPassword())) {
		// sr.setResult("请输入密码");
		// return sr;
		// }
		// if (userDto.getPassword().length() < 6 || userDto.getPassword().length() >
		// 18) {
		// sr.setResult("密码长度为6-18位");
		// return sr;
		// }
		userDto.setPassword(null);// 关闭密码

		if (StringUtils.isBlank(type)) {
			sr.setResult("业务关系代码类型不能为空，请debug");
			return sr;
		}

		String agrementNo = userDto.getAgrementNo();// 业务关系代码
		String saleCode = userDto.getSaleCode();// 销售人员编码
		String saleName = userDto.getSaleName();// 销售人员名称

		boolean isNeWUser = false;// 是否是新账户
		TbSpUser userExisting = null;// 是否已存在的用户

		if (StringUtils.isBlank(userDto.getWxOpenId())) {
			// 新开户校验

			List<TbSpUser> oldUsers = userDao.findByMobile(userDto.getMobile());
			if (CollectionUtils.isNotEmpty(oldUsers) || oldUsers.size() > 0) {
				sr.setResult("您输入的手机号码已被使用");
				return sr;
			}
			// 相同账户类型 - 校验身份证号码是否重复
			List<TbSpUser> users = userDao.findByIdNumber(userDto.getIdNumber(), userDto.getRegisterType());
			if (CollectionUtils.isNotEmpty(users) || users.size() > 0) {
				sr.setResult("您输入的证件号码已被使用");
				return sr;
			}
		} else {
			// 微信已登录的账户校验

			List<TbSpUser> spUsers = userDao.findByWxOpenId(userDto.getWxOpenId());
			if (CollectionUtils.isEmpty(spUsers)) {
				sr.setResult("已登录的微信账户已失效");
				return sr;
			}
			userExisting = spUsers.get(0);
			if (StringUtils.isNotBlank(userExisting.getStoreFlag()) && userExisting.getStoreFlag().equals(Constants.USER_STORE_FLAG_1)) {
				sr.setResult("您已经是店主，无需重复开店");
				return sr;
			}
		}

		if (userExisting == null) {
			isNeWUser = true;// 新账户
		}
		// 准备入库或改库的用户对象
		TbSpUser insertUser = new TbSpUser();// 新用户创建对象
		if (!isNeWUser) {
			insertUser = userExisting;// 已存在的用户对象
		}
		// 根据传参类型确认校验类型
		switch (type) {
		case "input":
			// 校验输入的关系代码信息是否被篡改
			Object obj = redis.get(Constants.AGREEMEN_TINFO + request.getSession().getId());
			if (null == obj) {
				sr.setAppFail("请求超时");
				return sr;
			}
			// 业务关系代码
			PrpLmAgent prpLmAgent = (PrpLmAgent) obj;
			sr = shopService.checkAgreementNo(request, sr, Constants.AGREEMENT_NO_INPUT, prpLmAgent, insertUser, agrementNo, saleCode, saleName,
					null);
			break;
		case "select":
			// 查询的常住地信息
			TbSysHotarea hotarea = hotareaDao.findByAreaName(userDto.getAreaName());
			if (null == hotarea) {
				sr.setResult("当前常驻地区不存在");
				return sr;
			}
			sr = shopService.checkAgreementNo(request, sr, Constants.AGREEMENT_NO_SELECTAREA, null, insertUser, agrementNo, saleCode, saleName,
					hotarea);
			break;
		default:
			sr.setResult("请提供业务关系代码类型");
			return sr;
		}

		if (sr.getState() != ServiceResult.STATE_SUCCESS) {
			return sr;// 验证失败
		}

		if (isNeWUser) {

			// 创建新的账户==================================================================

			userDto.setBranchCode(insertUser.getBranchCode());
			userDto.setAgrementNo(insertUser.getAgrementNo());
			userDto.setAgrementName(insertUser.getAgrementName());
			userDto.setSaleCode(insertUser.getSaleCode());
			userDto.setSaleName(insertUser.getSaleName());
			userDto.setChannelCode(insertUser.getChannelCode());
			userDto.setChannelName(insertUser.getChannelName());
			userDto.setAreaCode(insertUser.getAreaCode());// 常驻地区编码
			userDto.setAreaName(insertUser.getAreaName());// 常驻地区名称
			userDto.setCustomerType(insertUser.getChannelType());// 客户单位类型
			userDto.setCustomerName(insertUser.getCustomName());// 客户单位名称
			userDto.setCanModify("1");// 默认允许修改店铺信息
			if (StringUtils.isNotBlank(userDto.getRegisterType())) {
				if (userDto.getRegisterType().equals(Constants.USER_REGISTER_TYPE_2)) {// 分享注册的末级渠道
					userDto.setCanModify("0");// 不允许修改店铺信息
				}
			} else {
				userDto.setRegisterType("0");// 默认0=wx自主/分享注册(个人用户)
			}

			userDto.setComCode(superUser.getUserCode());// 上级渠道
			userDto.setIdType(Constants.USER_ID_CARD_TYPE_1);// 证件类型，1= 身份证号码

			insertUser = this.createFrontChannelUser(userDto);
			if (insertUser == null) {
				sr.setAppFail("注册失败[exception]");
				return sr;
			}
			// 创建账户成功
			sr.setResult(insertUser);
			sr.setSuccess();

		} else {

			// 已存在的账户升级==================================================================

			if (StringUtils.isBlank(insertUser.getEmployeeCode())) {
				insertUser.setEmployeeCode(userDto.getEmployeeCode());
			}
			if (StringUtils.isBlank(insertUser.getUserName())) {
				insertUser.setUserName(userDto.getUserName());
			}
			if (StringUtils.isBlank(insertUser.getMobile())) {
				insertUser.setMobile(userDto.getMobile());
			}
			if (StringUtils.isBlank(insertUser.getIdNumber())) {
				insertUser.setIdNumber(userDto.getIdNumber());
				insertUser.setIdType(Constants.USER_ID_CARD_TYPE_1);// 证件类型，1= 身份证号码
			} else {
				if (StringUtils.isBlank(insertUser.getIdType())) {
					insertUser.setIdType(Constants.USER_ID_CARD_TYPE_1);// 证件类型，1= 身份证号码
				}
			}

			insertUser.setCanModify("1");// 默认允许修改店铺信息
			if (StringUtils.isNotBlank(userDto.getRegisterType())) {
				if (userDto.getRegisterType().equals(Constants.USER_REGISTER_TYPE_2)) {// 分享注册的末级渠道
					insertUser.setCanModify("0");// 不允许修改店铺信息
				}
			} else {
				insertUser.setRegisterType("0");// 默认0=wx自主/分享注册(个人用户)
			}

			insertUser.setShopName(userDto.getShopName());
			// insertUser.setBranchCode(userDto.getBranchCode());// 机构编码
			// insertUser.setAgrementNo(userDto.getAgrementNo());// 业务关系代码
			// insertUser.setAgrementName(userDto.getAgrementName());// 代理名称
			// insertUser.setSaleCode(userDto.getSaleCode());// 销售人员编码
			// insertUser.setSaleName(userDto.getSaleName());// 销售人员名称
			// insertUser.setChannelCode(userDto.getChannelCode());// 渠道编码
			// insertUser.setChannelName(userDto.getChannelName());// 渠道名称
			// insertUser.setAreaCode(userDto.getAreaCode());// 常驻地区编码
			// insertUser.setAreaName(userDto.getAreaName());// 常驻地区名称
			// insertUser.setChannelType(userDto.getCustomerType());// 客户单位类型
			// insertUser.setCustomName(userDto.getCustomerName());// 客户单位名称

			insertUser.setComCode(superUser.getUserCode());// 上级渠道
			// 开店
			if (StringUtils.isBlank(insertUser.getStoreFlag()) || !insertUser.getStoreFlag().equals("1")) {
				insertUser.setStoreFlag("1");
				insertUser.setStoreCreateTime(new Timestamp(new Date().getTime()));
			}

			sr.setResult(userDao.save(insertUser));
			sr.setSuccess();
		}

		TbSpSaleLog saleLog = new TbSpSaleLog();// 日志
		saleLog.setOperation(TbSpSaleLog.CHANNEL_REGISTER);
		saleLog.setUserCode(insertUser.getUserCode());
		saleLog.setMark("邀请的好友" + (isNeWUser ? "【注册】" : "【升级】账户类型") + "[" + insertUser.getRegisterType() + "]成功");
		saleLog.setRequestTime(new Date());
		saleLog.setRequestData("邀请人:" + superUser.getUserCode() + ",id：" + superUser.getId() + ",userName：" + superUser.getUserName());
		saleLog.setResponseData(JSON.toJSONString(sr.getResult()));
		spSaleLogDao.save(saleLog);

		// 推送微信消息
		if (sr.getState() == ServiceResult.STATE_SUCCESS) {
			// 通知内容
			String contents = String.format(Constants.SMS_BY_ACCEPT_REGISTER, insertUser.getUserName());
			boolean flag = weChatService.sendTextMessageSingle(superUser.getWxOpenId(), MessageType.REQ_MESSAGE_TYPE_TEXT, contents);

			saleLog = new TbSpSaleLog();// 日志
			saleLog.setOperation(TbSpSaleLog.WECHAT_MSG);
			saleLog.setUserCode(superUser.getUserCode());
			saleLog.setMark("邀请的好友" + (isNeWUser ? "【注册】" : "【升级】账户类型") + "[" + insertUser.getRegisterType() + "]成功");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("邀请人:" + superUser.getUserCode() + ",id：" + superUser.getId() + ",userName：" + superUser.getUserName());
			saleLog.setResponseData("推送结果[" + flag + "]，内容：" + JSON.toJSONString(contents));
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Override
	public ServiceResult saveWeChatUser(ServiceResult sr, WeChatUser weChatUser, String refereeId, String refereePro) throws Exception {
		sr.setAppFail("保存失败");
		List<TbSpUser> users = userDao.findByWxOpenId(weChatUser.getOpenid());
		if (CollectionUtils.isNotEmpty(users) || users.size() == 1) {
			// "已授权登录"
			TbSpUser user = users.get(0);

			// 映射属性
			if (weChatService.copyWeChatToBbean(weChatUser, user, false)) {
				userDao.save(user);// 更新微信信息
			}
			user.setBanks(this.getAllBank(user));// 查询银行卡列表

			sr.setResult(user);
			return sr;
		}
		UserDto userDto = new UserDto();
		userDto.setRefereeId(refereeId);
		userDto.setRefereePro(refereePro);

		sr.setResult(this.createUser(userDto, weChatUser));
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult saveWeChatToBsUser(ServiceResult sr, WeChatUser weChatUser, String superUserCode, String oathType) throws Exception {
		sr.setAppFail("保存账户失败[copy]");
		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.CHANNEL_REGISTER);
		saleLog.setRequestTime(new Date());
		saleLog.setRequestData("分享人superUserCode:" + superUserCode + ",当前账户usercode：" + oathType + ",新获取的微信信息：" + JSON.toJSONString(weChatUser));

		// 渠道注册刚开的账户
		TbSpUser oldChannelUser = userDao.findByUserCode(oathType);

		if (oldChannelUser == null) {
			saleLog.setMark(TbSpSaleLog.CHANNEL_REGISTER + "[未查询到渠道注册刚新开的账户]");// 日志
		} else {
			saleLog.setUserCode(oldChannelUser.getUserCode());// 日志

			List<TbSpUser> weChatUsers = userDao.findByWxOpenId(weChatUser.getOpenid());
			if (CollectionUtils.isNotEmpty(weChatUsers) || weChatUsers.size() > 0) {
				// "已授权"
				TbSpUser oldWeChatUser = weChatUsers.get(0);
				// 已授权的微信账户未开店
				if (StringUtils.isBlank(oldWeChatUser.getStoreFlag()) || !Constants.USER_STORE_FLAG_1.equals(oldWeChatUser.getStoreFlag())) {

					if ((StringUtils.isBlank(oldWeChatUser.getMobile()) && StringUtils.isBlank(oldWeChatUser.getIdNumber()))
							|| oldChannelUser.getMobile().equals(oldWeChatUser.getMobile())
							|| oldChannelUser.getIdNumber().equals(oldWeChatUser.getIdNumber())) {
						// 原授权的微信账户若 [手机号或证件号都为空] 或者
						// [手机号或证件号二者其一相同](则表示同一个身份)时，升级为店铺（信息覆盖到旧账户）

						// BeanUtilExt.copybean1ToBbean2(oldChannelUser, oldWeChatUser);

						oldWeChatUser.setUserName(oldChannelUser.getUserName());// 姓名
						oldWeChatUser.setMobile(oldChannelUser.getMobile());// 手机号
						oldWeChatUser.setIdNumber(oldChannelUser.getIdNumber());// 证件号
						oldWeChatUser.setIdType(oldChannelUser.getIdType());// 证件类型
						oldWeChatUser.setRegisterType(oldChannelUser.getRegisterType());// 分享时注册的类型
						oldWeChatUser.setComCode(oldChannelUser.getComCode());// 上级渠道

						oldWeChatUser.setShopName(oldChannelUser.getShopName());// 店铺名称
						oldWeChatUser.setBranchCode(oldChannelUser.getBranchCode());// 机构编码
						oldWeChatUser.setAgrementNo(oldChannelUser.getAgrementNo());// 业务关系代码
						oldWeChatUser.setAgrementName(oldChannelUser.getAgrementName());// 代理名称
						oldWeChatUser.setSaleCode(oldChannelUser.getSaleCode());// 销售人员编码
						oldWeChatUser.setSaleName(oldChannelUser.getSaleName());// 销售人员名称
						oldWeChatUser.setChannelCode(oldChannelUser.getChannelCode());// 渠道编码
						oldWeChatUser.setChannelName(oldChannelUser.getChannelName());// 渠道名称
						oldWeChatUser.setAreaCode(oldChannelUser.getAreaCode());// 常驻地区编码
						oldWeChatUser.setAreaName(oldChannelUser.getAreaName());// 常驻地区名称
						oldWeChatUser.setChannelType(oldChannelUser.getChannelType());// 客户单位类型
						oldWeChatUser.setCustomName(oldChannelUser.getCustomName());// 客户单位名称
						oldWeChatUser.setCanModify(oldChannelUser.getCanModify());// 是否允许修改店铺信息
						if (!Constants.USER_STORE_FLAG_1.equals(oldWeChatUser.getStoreFlag())) {
							oldWeChatUser.setStoreFlag(Constants.USER_STORE_FLAG_1);// 开店
						}
						userDao.save(oldWeChatUser);// 升级为分享注册的账户，并开店

						// 刚新开的渠道账户状态关闭
						oldChannelUser.setState(Constants.USER_STATE_0);
						userDao.save(oldChannelUser);

						saleLog.setMark(TbSpSaleLog.CHANNEL_REGISTER + "[将新新开户的渠道账户信息copy到 - 已授权的旧微信账户]【原授权的微信账户若 [手机号或证件号都为空] "
								+ "或者 [手机号或证件号二者其一相同](则表示同一个身份)时，升级为店铺（信息覆盖到旧账户）】");
						saleLog.setResponseData(JSON.toJSONString(oldWeChatUser));
						saleLog.setUserCode(oldWeChatUser.getUserCode());// 日志

					} else {
						saleLog.setMark(TbSpSaleLog.CHANNEL_REGISTER + "[已新开的渠道账户与已授权的微信账户独立无关系]");
						// 已新开的渠道账户与已授权的微信账户独立无关系
					}
				} else {
					// 旧微信账户已开店，即已新开的渠道账户与已授权的微信账户独立无关系
					saleLog.setMark(TbSpSaleLog.CHANNEL_REGISTER + "[旧微信账户已开店，即已新开的渠道账户与已授权的微信账户独立无关系]");
				}
			} else {
				// 渠道注册新开户时，该用户未授权过微信账户
				boolean copyResult = weChatService.copyWeChatToBbean(weChatUser, oldChannelUser, true);// 映射属性
				if (copyResult) {
					userDao.save(oldChannelUser);// 更新微信信息

					sr.setResult(oldChannelUser);
					sr.setSuccess();

					saleLog.setMark(TbSpSaleLog.CHANNEL_REGISTER + "[将新获取的微信信息copy到 - 当前注册的渠道账户]");
					saleLog.setResponseData(JSON.toJSONString(oldChannelUser));
				}
			}
		}
		spSaleLogDao.save(saleLog);
		return sr;
	}

	@Override
	public ServiceResult initUserPwd(ServiceResult sr, String userCode, String password, String confirmPassword) throws Exception {
		sr.setAppFail("初始密码失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		if (StringUtils.isBlank(password)) {
			sr.setResult("请输入密码");
			return sr;
		}
		if (StringUtils.isBlank(confirmPassword)) {
			sr.setResult("请输入确认密码");
			return sr;
		}
		if (password.trim().length() < 6 || password.trim().length() > 18 || confirmPassword.trim().length() < 6
				|| confirmPassword.trim().length() > 18) {
			sr.setResult("密码长度为6-18位");
			return sr;
		}
		Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
		// 加密密码
		password = md5PwdEncoder.encodePassword(password);
		// 根据用户编码设置密码
		int updateNo = userDao.initUserPwd(password, userCode);
		if (updateNo == 1) {
			sr.setResult("密码设置成功");
			sr.setSuccess();
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updatePwdByMobile(ServiceResult sr, String userCode, String mobile, String password) throws Exception {
		sr.setAppFail("密码修改失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		if (StringUtils.isBlank(password)) {
			sr.setResult("请输入新密码");
			return sr;
		}
		if (password.trim().length() < 6 || password.trim().length() > 18) {
			sr.setResult("密码长度为6-18位");
			return sr;
		}
		TbSpUser tbSpUser = userDao.findByUserCode(userCode);
		if (tbSpUser == null) {
			sr.setResult("用户不存在");
			return sr;
		}
		if (!mobile.equals(tbSpUser.getMobile())) {
			sr.setResult("手机号不匹配");
			return sr;
		}
		Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
		// 校验原密码
		if (md5PwdEncoder.isPasswordValid(tbSpUser.getPassword(), password)) {
			sr.setResult("新密码不能和原密码相同");
			return sr;
		}
		// 加密新密码
		password = md5PwdEncoder.encodePassword(password);
		// 修改
		int updateNo = userDao.updatePwdByUserCode(password, userCode);
		if (updateNo == 1) {
			sr.setResult("密码修改成功");
			sr.setSuccess();
			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_PASSWORD);
			saleLog.setMark(TbSpSaleLog.UP_PASSWORD);
			saleLog.setUserCode(userCode);
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("userCode:" + userCode + ",mobile：" + mobile + ",password：" + password);
			saleLog.setResponseData("原密码:" + tbSpUser.getPassword() + ",新密码：" + password);
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateIdNumberByMobile(ServiceResult sr, String userCode, String userName, String idNumber) throws Exception {
		sr.setAppFail("实名认证失败");
		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		if (StringUtils.isBlank(userName)) {
			sr.setResult("请输入真实姓名");
			return sr;
		}
		if (userName.length() < 2) {
			sr.setResult("姓名至少2个字符");
			return sr;
		}
		if (userName.length() > 50) {
			sr.setResult("姓名最多50个字符");
			return sr;
		}
		if (!StringUtil.isAllChinese(userName)) {
			sr.setResult("真实姓名只能是中文");
			return sr;
		}
		if (StringUtils.isBlank(idNumber)) {
			sr.setResult("请输入身份证号码");
			return sr;
		}
		if (idNumber.trim().length() < 15 || idNumber.trim().length() > 18) {
			sr.setResult("证件号码长度为15-18个字符");
			return sr;
		}
		TbSpUser tbSpUser = userDao.findByUserCode(userCode);
		if (tbSpUser == null) {
			sr.setResult("用户不存在");
			return sr;
		}
		if (userName.equals(tbSpUser.getUserName()) && idNumber.equals(tbSpUser.getIdNumber())) {
			sr.setResult("您已经实名认证");
			return sr;
		}
		// 不是旧身份证号码
		List<TbSpUser> users = userDao.findByIdNumber(idNumber);
		for (TbSpUser user : users) {
			if (user.getId().compareTo(tbSpUser.getId()) != 0 && idNumber.equals(user.getIdNumber())) {
				sr.setResult("您输入的证件号码已被认证");
				return sr;
			}
		}
		// 修改
		int updateNo = userDao.updateRealNameByUserCode(userName, idNumber, Constants.USER_ID_CARD_TYPE_1, userCode);
		if (updateNo == 1) {
			tbSpUser.setUserName(userName);
			tbSpUser.setIdNumber(idNumber);
			tbSpUser.setIdType(Constants.USER_ID_CARD_TYPE_1);// 证件类型

			// 查询该用户所有有效的银行卡
			tbSpUser.setBanks(this.getAllBank(tbSpUser));

			sr.setResult(tbSpUser);
			sr.setSuccess();

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_REALNAME);
			saleLog.setUserCode(userCode);
			saleLog.setMark("实名认证_短信验证码");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("userCode:" + userCode + ",userName：" + userName + ",idNumber：" + idNumber);
			saleLog.setResponseData(JSON.toJSONString(tbSpUser));
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult unbindIdNumberByMobile(ServiceResult sr, String userCode, String idNumber) throws Exception {
		sr.setAppFail("解绑失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		if (StringUtils.isBlank(idNumber)) {
			sr.setResult("身份证号码为空");
			return sr;
		}
		if (!(idNumber.trim().length() == 15 || idNumber.trim().length() == 18)) {
			sr.setResult("身份证号码为15或18位");
			return sr;
		}
		List<TbSpUser> users = userDao.findAll(new Specification<TbSpUser>() {
			public Predicate toPredicate(Root<TbSpUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicate = new ArrayList<Predicate>();
				predicate.add(cb.equal(root.get("idNumber").as(String.class), idNumber));
				predicate.add(cb.equal(root.get("userCode").as(String.class), userCode));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		});

		if (CollectionUtils.sizeIsEmpty(users)) {
			sr.setResult("证件号[" + idNumber.substring(0, 5) + "**********" + idNumber.substring(idNumber.length() - 3, idNumber.length()) + "]不存在");
			return sr;
		}

		TbSpUser tbSpUser = users.get(0);
		// 修改
		int updateNo = userDao.updateRealNameByUserCode(null, null, null, userCode);
		if (updateNo == 1) {
			tbSpUser.setIdNumber(null);

			// 查询该用户所有有效的银行卡
			tbSpUser.setBanks(this.getAllBank(tbSpUser));

			sr.setResult(tbSpUser);
			sr.setSuccess();

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_REALNAME);
			saleLog.setUserCode(userCode);
			saleLog.setMark("解绑实名认证_短信验证码 & 图形码");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("userCode:" + userCode + ",idNumber：" + idNumber);
			saleLog.setResponseData(JSON.toJSONString(tbSpUser));
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Override
	public ServiceResult updateUserName(ServiceResult sr, String userCode, String userName) throws Exception {
		sr.setAppFail("姓名修改失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		if (StringUtils.isBlank(userName)) {
			sr.setResult("请输入新姓名");
			return sr;
		}
		if (userName.length() < 2 || userName.length() > 10) {
			sr.setResult("姓名长度为2-10位");
			return sr;
		}
		Pattern p = Pattern.compile(Constants.REGEX_SPECIALCHARACTERS_CODE);
		Matcher m = p.matcher(userName);
		if (m.find()) {
			sr.setResult("姓名不能包含特殊字符");
			return sr;
		}
		TbSpUser tbSpUser = userDao.findByUserCode(userCode);
		if (tbSpUser == null) {
			sr.setResult("用户不存在");
			return sr;
		}
		// 修改
		int updateNo = userDao.updateUserNameByUserCode(userName, userCode);
		if (updateNo == 1) {
			tbSpUser.setUserName(userName);

			// 查询该用户所有有效的银行卡
			tbSpUser.setBanks(this.getAllBank(tbSpUser));

			sr.setResult(tbSpUser);
			sr.setSuccess();
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateMobile(RedisUtils redis, ServiceResult sr, String userCode, String mobile) throws Exception {
		sr.setAppFail("手机号修改失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}

		// 查询用户
		TbSpUser tbSpUser = userDao.findByUserCode(userCode);
		if (tbSpUser == null) {
			sr.setResult("用户不存在");
			return sr;
		}

		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.UP_MOBILE);
		saleLog.setUserCode(userCode);
		saleLog.setRequestTime(new Date());
		saleLog.setRequestData("userCode:" + userCode + ",mobile：" + mobile);

		// 设置手机号，已存在的需要提示合并
		List<TbSpUser> tbSpUsers = userDao.findByMobile(mobile);
		if (CollectionUtils.isEmpty(tbSpUsers)) {
			// 设置手机号
			int updateNo = userDao.updateMobileByUserCode(mobile, userCode);
			if (updateNo == 1) {
				tbSpUser.setMobile(mobile);

				// 查询该用户所有有效的银行卡
				tbSpUser.setBanks(this.getAllBank(tbSpUser));

				sr.setResult(tbSpUser);
				sr.setSuccess();

				saleLog.setMark("修改手机号");
				saleLog.setResponseData(JSON.toJSONString(tbSpUser));
				spSaleLogDao.save(saleLog);
			}
			return sr;
		}
		for (TbSpUser user : tbSpUsers) {
			// 自己的账户
			if (user.getId().compareTo(tbSpUser.getId()) == 0) {
				// 更换手机号
				if (StringUtils.isNotBlank(tbSpUser.getMobile())) {
					if (tbSpUser.getMobile().equals(mobile)) {
						sr.setResult("请使用新手机号码");
						return sr;
					}
					// 更换手机号
					int updateNo = userDao.updateMobileByUserCode(mobile, userCode);
					if (updateNo == 1) {
						tbSpUser.setMobile(mobile);

						// 查询该用户所有有效的银行卡
						tbSpUser.setBanks(this.getAllBank(tbSpUser));

						sr.setResult(tbSpUser);
						sr.setSuccess();

						saleLog.setMark("更换手机号");
						saleLog.setResponseData(JSON.toJSONString(tbSpUser));
						spSaleLogDao.save(saleLog);

						return sr;
					}
				}
			} else {
				// 手机号相同,用户编码不同,说明是同一个人的用户
				if (user.getMobile().equals(mobile)) {
					String keyVal = new Md5PwdEncoder().encodePassword(userCode + mobile);
					redis.setStringWithExpireTime(userCode, keyVal + "," + user.getUserCode(), Constants.SINGLE_REQUEST_TIMEOUT_SECONDS);
					String no = mobile.substring(0, 3) + "*****" + mobile.substring(mobile.length() - 3, mobile.length());
					sr.setResult("是否与用户[" + no + "]合并 ?");
					return sr;
				}
			}
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateUserFormerge(RedisUtils redis, ServiceResult sr, String userCode, String mobile) throws Exception {
		sr.setAppFail("合并用户失败");

		if (StringUtils.isBlank(userCode) || StringUtils.isBlank(mobile)) {
			sr.setResult("参数无效");
			return sr;
		}

		String strings = redis.getString(userCode);
		if (StringUtils.isBlank(strings)) {
			sr.setResult("请重新输入信息提交");
			return sr;
		}
		// 校验参数
		String keyVal = strings.split(",")[0];
		String redisUserCode = strings.split(",")[1];
		if (!new Md5PwdEncoder().isPasswordValid(keyVal, userCode + mobile)) {
			sr.setResult("请正确提交上一步信息");
			return sr;
		}
		redis.deletelike(userCode);// 清除当前操作使用的内容

		// 查询用户1
		TbSpUser user1 = userDao.findByUserCode(userCode);
		// 查询用户2
		TbSpUser user2 = userDao.findByUserCode(redisUserCode);
		if (user1 == null || user2 == null) {
			sr.setResult("用户不存在");
			return sr;
		}

		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.UP_MERGE);
		saleLog.setUserCode(userCode);
		saleLog.setRequestTime(new Date());
		saleLog.setRequestData("userCode:" + userCode + ",mobile：" + mobile);

		if (StringUtils.isBlank(user2.getWxOpenId())) {// 没有openID=浏览器账户,关闭user2账户
			// 关闭user2账户
			user1 = mergeUser(user2, user1);
			sr.setResult(user1);
			sr.setSuccess();

			saleLog.setMark("被查手机号[不是]微信账户，合并到当前账户上");
			saleLog.setResponseData(JSON.toJSONString(user1));
			spSaleLogDao.save(saleLog);

			return sr;
		}
		// 关闭user1账户
		user2 = mergeUser(user1, user2);
		sr.setResult(user2);
		sr.setSuccess();

		saleLog.setMark("被查手机号[是]微信账户，合并到输入的手机号对应账户上");
		saleLog.setResponseData(JSON.toJSONString(user2));
		spSaleLogDao.save(saleLog);

		return sr;
	}

	/**
	 * Remarks: 合并用户<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2018年1月25日下午5:11:52<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param userClose
	 *            关闭账户
	 * @param userHold
	 *            持久账户
	 * @return
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private TbSpUser mergeUser(TbSpUser userClose, TbSpUser userHold)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		// 更新银行卡信息
		// 查询该用户所有有效的银行卡
		List<TbSpBank> banks = this.getAllBank(userClose);
		if (CollectionUtils.isNotEmpty(banks)) {

			// 修改当前账户所有银行卡为非默认
			for (TbSpBank bank : banks) {
				if (bank.getIsDefault().compareTo(1) == 0) {
					bankDao.updateStateByUserCode(new Date(), bank.getUnbundingTime(), 0, bank.getUserCode());
					break;
				}
			}

			bankDao.updateUserCodeByUserCode(new Date(), userHold.getUserCode(), userClose.getUserCode());
		}

		Date dateTime = new Date();
		// 提现记录
		int num = cashLogDao.updateUserCodeByUserCode(userHold.getUserCode(), userHold.getMobile(), userClose.getUserCode(), userClose.getMobile());
		this.saveLog(userClose, userHold, num, "提现", dateTime);

		// 抽奖记录
		num = drawLogDao.updateUserCodeByUserCode(userHold.getUserCode(), userHold.getMobile(), userClose.getUserCode(), userClose.getMobile());
		this.saveLog(userClose, userHold, num, "抽奖", dateTime);

		// 手工积分明细记录
		num = manualDetailDao.updateUserCodeByUserCode(userHold.getUserCode(), userHold.getMobile(), userClose.getUserCode(), userClose.getMobile());
		this.saveLog(userClose, userHold, num, "手工积分明细", dateTime);

		// 积分收入记录
		num = scoreLogInDao.updateUserCodeByUserCode(userHold.getUserCode(), userHold.getMobile(), userClose.getUserCode(), userClose.getMobile());
		this.saveLog(userClose, userHold, num, "积分收入", dateTime);

		// 积分消费记录
		num = scoreLogOutDao.updateUserCodeByUserCode(userHold.getUserCode(), userHold.getMobile(), userClose.getUserCode(), userClose.getMobile());
		this.saveLog(userClose, userHold, num, "积分消费", dateTime);

		// 旧账户已存在总积分记录
		List<TbSpScore> scoreList = scoreDao.findByUserCode(userClose.getUserCode());
		if (CollectionUtils.isNotEmpty(scoreList)) {
			TbSpScore oldscore = scoreList.get(0);
			// 新账户已存在总积分记录
			num = scoreDao.findCountByUserCode(userHold.getUserCode());

			StringBuffer prefix = new StringBuffer("保留的账户[" + userHold.getUserCode() + "]");
			if (num > 0) {
				// 新账户累加积分
				scoreDao.updateScoreByUserCode(oldscore.getEffctiveScore(), oldscore.getNoeffctiveScore(), oldscore.getSumScore(),
						userHold.getUserCode());
				// 旧账户积分清零
				scoreDao.updateScoreByUserCode(0.0D, 0.0D, 0.0D, userClose.getUserCode());
				prefix.append("累加");
			} else {
				TbSpScore newScore = new TbSpScore();
				newScore.setEffctiveScore(oldscore.getEffctiveScore());
				newScore.setNoeffctiveScore(oldscore.getNoeffctiveScore());
				newScore.setStatisticTime(oldscore.getStatisticTime());
				newScore.setSumScore(oldscore.getSumScore());
				// 被关闭账户openID为空使用新账户
				newScore.setOpenid(StringUtils.isNotEmpty(userClose.getWxOpenId()) ? userClose.getWxOpenId() : null);
				newScore.setOpenid(StringUtils.isNotEmpty(userHold.getWxOpenId()) ? userHold.getWxOpenId() : null);
				newScore.setUserCode(userHold.getUserCode());
				newScore.setPhoneNo(userHold.getMobile());
				scoreDao.save(newScore);
				// 旧账户积分清零
				scoreDao.updateScoreByUserCode(0.0D, 0.0D, 0.0D, userClose.getUserCode());
				prefix.append("使用关闭的账户的积分信息创建新的积分记录");
			}

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_MERGE);
			saleLog.setUserCode(userHold.getUserCode());
			saleLog.setRequestTime(dateTime);
			saleLog.setRequestData(JSON.toJSONString(oldscore));
			saleLog.setMark("关闭账户[" + userClose.getUserCode() + "]，合并到账户[" + userHold.getUserCode() + "]");

			prefix.append("，有效积分=" + oldscore.getEffctiveScore());
			prefix.append("，待生效积分=" + oldscore.getNoeffctiveScore());
			prefix.append("，总积分=" + oldscore.getSumScore());
			prefix.append("<br><br>关闭的账户[" + userClose.getUserCode() + "]积分清零");
			saleLog.setResponseData(prefix.toString());
			spSaleLogDao.save(saleLog);
		}

		String userType = userHold.getUserType();
		// 被合并的账户将被覆盖业务关系代码
		if (StringUtils.isBlank(userHold.getAgrementNo()) && StringUtils.isNotBlank(userClose.getAgrementNo())) {
			userType = userClose.getUserType();// 用户类型依次覆盖
		}

		// 将对象1的属性值映射到对象2中，只映射对象2属性值为空的属性
		BeanUtilExt.reflectAbeanToBbean(userClose, userHold);

		// 记录openId
		if (StringUtils.isNotBlank(userHold.getWxOpenId())) {
			userClose.setWxOpenId(userHold.getWxOpenId());
		}
		// 注销用户1
		userClose.setState("0");
		userClose = userDao.save(userClose);

		// 设置第二编码
		userHold.setUserCodeBs(userClose.getUserCode());
		userHold.setMobile(userClose.getMobile());
		userHold.setUserType(userType);
		userHold = userDao.save(userHold);

		// 合并用户店铺信息
		userHold = shopService.mergeAccount(userHold.getUserCode());
		// 查询该用户所有有效的银行卡
		userHold.setBanks(banks);
		return userHold;
	}

	private void saveLog(TbSpUser userClose, TbSpUser userHold, int num, String title, Date dateTime) {
		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.UP_MERGE);
		saleLog.setUserCode(userHold.getUserCode());
		saleLog.setRequestTime(dateTime);
		saleLog.setRequestData("userHold=" + userHold.getUserCode() + "-" + userHold.getMobile() + ",userClose=" + userClose.getUserCode() + "-"
				+ userClose.getMobile());
		saleLog.setMark("关闭账户[" + userClose.getUserCode() + "]，合并到账户[" + userHold.getUserCode() + "]");
		saleLog.setResponseData("更新[" + num + "]条【" + title + "】记录的用户编码和手机号");
		spSaleLogDao.save(saleLog);
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult loginByMobile(HttpServletRequest request, ServiceResult sr, String mobile, String refereeId, String refereePro)
			throws Exception {
		sr.setAppFail("手机登录失败");

		List<TbSpUser> oldUsers = userDao.findByMobile(mobile);
		if (CollectionUtils.isEmpty(oldUsers)) {

			UserDto userDto = new UserDto();
			userDto.setMobile(mobile);
			userDto.setRefereeId(refereeId);
			userDto.setRefereePro(refereePro);

			sr.setResult(this.createUser(userDto, null));
			// sr.setResult("账户不存在");
			sr.setSuccess();
			return sr;
		}
		if (oldUsers.size() == 1) {
			TbSpUser user = this.updateByLogin(request, sr, null, oldUsers.get(0));
			if (user != null) {
				// 登录成功
				// 查询该用户所有有效的银行卡
				user.setBanks(this.getAllBank(user));
				sr.setResult(user);
				sr.setSuccess();

				TbSpSaleLog saleLog = new TbSpSaleLog();
				saleLog.setOperation(TbSpSaleLog.UP_LOGIN);
				saleLog.setUserCode(user.getUserCode());
				saleLog.setMark("登录_短信验证码");
				saleLog.setRequestTime(new Date());
				saleLog.setRequestData("mobile:" + mobile + ",refereeId：" + refereeId + ",refereePro：" + refereePro);
				saleLog.setResponseData(JSON.toJSONString(user));
				spSaleLogDao.save(saleLog);
			}
		} else {
			String str = mobile.substring(0, 3) + "*****" + mobile.substring(mobile.length() - 3, mobile.length());
			sr.setResult("手机号[" + str + "]已被使用");
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult loginBypassword(HttpServletRequest request, ServiceResult sr, String mobile, String password) throws Exception {
		// 校验手机号是否有效
		sr = smsService.phoneNumCheckForLogin(sr, mobile);
		if (sr.getState() != ServiceResult.STATE_SUCCESS) {
			return sr;
		}
		sr.setAppFail("密码登录失败");

		if (StringUtils.isBlank(password)) {
			sr.setAppFail("请输入密码");
			return sr;
		}
		if (password.length() < 6 || password.length() > 18) {
			sr.setAppFail("密码长度为6-18位");
			return sr;
		}
		// 根据手机号查找用户
		List<TbSpUser> oldUsers = userDao.findByMobile(mobile);
		if (CollectionUtils.sizeIsEmpty(oldUsers)) {
			sr.setAppFail("用户不存在");
			return sr;
		}
		if (oldUsers.size() != 1) {
			sr.setAppFail("存在多个手机号为[" + mobile + "]的用户");
			return sr;
		}
		TbSpUser spUser = oldUsers.get(0);
		// 校验密码
		Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
		if (!md5PwdEncoder.isPasswordValid(spUser.getPassword(), password)) {
			sr.setAppFail("密码错误");
			return sr;
		}

		TbSpUser user = this.updateByLogin(request, sr, null, oldUsers.get(0));
		if (user != null) {
			// 登录成功
			// 查询该用户所有有效的银行卡
			user.setBanks(this.getAllBank(user));

			sr.setResult(user);
			sr.setSuccess();

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_LOGIN);
			saleLog.setUserCode(user.getUserCode());
			saleLog.setMark("登录_密码");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("mobile:" + mobile + ",password：" + spUser.getPassword());
			saleLog.setResponseData(JSON.toJSONString(user));
			spSaleLogDao.save(saleLog);
		} else {
			sr.setAppFail("密码登录失败");
		}
		return sr;
	}

	/**
	 * Remarks: 更新登录信息<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2017年10月8日下午3:46:11<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param sr
	 * @param weChatUser
	 * @param user
	 * @return
	 */
	private TbSpUser updateByLogin(HttpServletRequest request, ServiceResult sr, WeChatUser weChatUser, TbSpUser user) {
		// 计算连续登录天数
		user = this.continuousLogin(user);
		// 更新登录信息
		Timestamp timestamp = new Timestamp(new Date().getTime());
		user.setLastloginDate(timestamp);
		user.setLoginTimes(user.getLoginTimes() + 1);

		if (null != weChatUser) {
			// 映射属性
			weChatService.copyWeChatToBbean(weChatUser, user, false);
		}

		TbSpUser saveUser = userDao.save(user);
		activityService.grantScore(saveUser.getBranchCode(), Constants.EXTENSION_ACTIVITY_DO, saveUser.getUserCode(), null);
		return saveUser;
	}

	/**
	 * Remarks: 计算连续登录天数<br>
	 * Version：1.0<br>
	 * Author：AoYi<br>
	 * DateTime：2018年1月3日上午11:49:29<br>
	 * Project：liberty_sale_plat<br>
	 * 
	 * @param user
	 * @return
	 */
	private TbSpUser continuousLogin(TbSpUser user) {
		Timestamp lastTimestamp = user.getLastloginDate();
		if (lastTimestamp == null) {
			lastTimestamp = user.getRegisteDate();
		}
		Date lastDate = new Date(lastTimestamp.getTime());// 最后一次登录时间
		Date todayDate = DateUtil.getStartTime(0);// 当日开始时间
		String lastDayStr = new SimpleDateFormat(DateUtil.DATE_TIME_PATTERN2).format(lastDate);
		String todayStr = new SimpleDateFormat(DateUtil.DATE_TIME_PATTERN2).format(todayDate);

		int differNo = DateUtil.dateDiff(todayStr, lastDayStr);
		// 相差不足一天
		if (differNo == 0) {
			// 上次登录时昨日则表示今天为连续登录
			if (lastDate.getTime() < todayDate.getTime()) {
				user.setLoginTimesContinuity(user.getLoginTimesContinuity() + 1);
				log.info("---------连续登录天数 + 1 ---------");
				// user = userDao.save(user);
				return user;
			} else {
				// 今日已登录过
				return user;
			}
		} else {
			// 相差1天即以上，重置连续登录天数
			user.setLoginTimesContinuity(0);
			return user;
		}
	}

	@Override
	public ServiceResult findUserByIdAndLogin(HttpServletRequest request, ServiceResult sr, Integer id) throws Exception {
		sr.setState(ServiceResult.STATE_EXCEPTION);
		sr.setResult(Constants.SYS_ERROR_MSG);
		if (new Integer(0).compareTo(id) <= 0) {
			Optional<TbSpUser> optional = userDao.findById(id);
			if (optional.isPresent()) {
				TbSpUser user = optional.get();
				user = this.updateByLogin(request, sr, null, user);
				if (user != null) {
					// 查询该用户所有有效的银行卡
					user.setBanks(this.getAllBank(user));
					sr.setResult(user);
					sr.setSuccess();
				} else {
					sr.setResult("用户不存在");
				}
			} else {
				sr.setResult("用户不存在");
			}
		} else {
			sr.setResult("id错误");
		}
		return sr;
	}

	@Override
	public ServiceResult findUserByUserCode(HttpServletRequest request, ServiceResult sr, String userCode) throws Exception {
		sr.setState(ServiceResult.STATE_EXCEPTION);
		sr.setResult(Constants.SYS_ERROR_MSG);
		if (StringUtils.isNotBlank(userCode)) {
			TbSpUser user = userDao.findByUserCode(userCode);
			if (user != null) {
				sr.setResult(user);
				sr.setSuccess();
			} else {
				sr.setResult("用户不存在");
			}
		} else {
			sr.setResult("usercode错误");
		}
		return sr;
	}

	@Override
	public ServiceResult findUserByComcode(HttpServletRequest request, ServiceResult sr, String comCode) throws Exception {
		sr.setState(ServiceResult.STATE_EXCEPTION);
		sr.setResult(Constants.SYS_ERROR_MSG);
		if (StringUtils.isNotBlank(comCode)) {
			TbSpUser user = userDao.findByUserCode(comCode);
			if (user != null) {
				sr.setResult(user);
				sr.setSuccess();
			} else {
				sr.setResult("上级用户不存在");
			}
		} else {
			sr.setResult("comCode错误");
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateUserByOpenId(HttpServletRequest request, ServiceResult sr, WeChatUser weChatUser, String openId) throws Exception {
		sr.setAppFail(Constants.SYS_ERROR_MSG);

		if (StringUtils.isBlank(openId)) {
			sr.setResult("openId为空");
		}
		List<TbSpUser> users = userDao.findByWxOpenId(openId);
		if (CollectionUtils.isNotEmpty(users) && users.size() == 1) {
			TbSpUser user = this.updateByLogin(request, sr, weChatUser, users.get(0));
			if (user != null) {
				// 微信登录成功
				// 查询该用户所有有效的银行卡
				user.setBanks(this.getAllBank(user));

				sr.setResult(user);
				sr.setSuccess();

				TbSpSaleLog saleLog = new TbSpSaleLog();
				saleLog.setOperation(TbSpSaleLog.UP_LOGIN);
				saleLog.setUserCode(user.getUserCode());
				saleLog.setMark("根据微信openID获取用户");
				saleLog.setRequestTime(new Date());
				saleLog.setRequestData("openId:" + openId + ",weChatUser：" + JSON.toJSONString(weChatUser));
				saleLog.setResponseData(JSON.toJSONString(user));
				spSaleLogDao.save(saleLog);
			}
		} else {
			sr.setResult("用户不存在");
		}
		return sr;
	}

	// 查询银行卡列表
	private List<TbSpBank> getAllBank(TbSpUser user) {
		// 查询该用户所有有效的银行卡
		List<TbSpBank> banks = new ArrayList<>();
		if (StringUtils.isNotBlank(user.getUserCodeBs())) {
			banks = bankDao.findAllByUserCode(user.getUserCode(), user.getUserCodeBs());
		} else {
			banks = bankDao.findAllByUserCode(user.getUserCode(), "-");
		}
		return banks;
	}

	@Override
	public ServiceResult findBankListAll(ServiceResult sr, String userCode) throws Exception {
		sr.setState(ServiceResult.STATE_EXCEPTION);
		sr.setResult(Constants.SYS_ERROR_MSG);
		if (StringUtils.isBlank(userCode)) {
			sr.setResult("用户编码无效");
			return sr;
		}
		Pattern p = Pattern.compile(Constants.REGEX_SPECIALCHARACTERS_CODE);
		Matcher m = p.matcher(userCode);
		if (m.find()) {
			sr.setResult("编码不能包含特殊字符");
			return sr;
		}
		TbSpUser user = new TbSpUser();
		user.setUserCode(userCode);
		// 查询该用户所有有效的银行卡
		sr.setResult(this.getAllBank(user));
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult findBankNoOfBinding(HttpServletRequest request, ServiceResult sr, RedisUtils redis, String userCode, String userName,
			String bankNumber, String province, String city, String bankBranchName) throws Exception {
		sr.setAppFail("银行卡号无效");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("用户编码无效");
			return sr;
		}
		if (StringUtils.isBlank(userName)) {
			sr.setResult("持卡人姓名不能为空");
			return sr;
		}
		if (StringUtils.isBlank(bankNumber)) {
			sr.setResult("银行卡号不能为空");
			return sr;
		}
		bankNumber = bankNumber.replaceAll(" ", "");// 清除空格
		if (!(bankNumber.length() == 16 || bankNumber.length() == 19)) {
			sr.setResult("银行卡号必须为16或19位");
			return sr;
		}
		if (StringUtils.isBlank(bankBranchName)) {
			sr.setResult("支行名称不能为空");
			return sr;
		}
		if (!(bankBranchName.length() >= 2 && bankNumber.length() <= 50)) {
			sr.setResult("银行卡号必须为2-50位");
			return sr;
		}
		if (StringUtils.isBlank(province)) {
			sr.setResult("请选择开户行所在省份");
			return sr;
		}
		if (StringUtils.isBlank(city)) {
			sr.setResult("请选择开户行所在市区");
			return sr;
		}
		TbSpUser user = userDao.findByUserCode(userCode);
		if (null == user) {
			sr.setResult("用户不存在");
			return sr;
		}
		if (!userName.equals(user.getUserName())) {
			sr.setResult("持卡人姓名必须与实名一致");
			return sr;
		}
		if (CheckBankCard.checkBankCard(bankNumber)) {
			// 查询某用户是否存在该卡号
			int number = bankDao.findByNumberAndUserCode(user.getUserCode(), bankNumber);
			if (number > 0) {
				sr.setResult("您已经绑定该卡，请注意查看");
				return sr;
			}
			// 查询卡号是否被其他账户绑定
			int otherUserBanks = bankDao.findByNumberOfOtherUser(user.getUserCode(), bankNumber);
			if (otherUserBanks > 0) {
				sr.setResult("该卡号已被其他账户使用");
				return sr;
			}
			// 获取卡号所属银行全称
			TbSpBank tbSpBank = new TbSpBank();
			tbSpBank.setUserCode(user.getUserCode());
			tbSpBank.setNumber(bankNumber);

			/**
			 * 
			 * 三方接口查询
			 * 
			 * 
			 * 
			 */

			TbSpBankCard bankCard = cardService.getBankCard(bankNumber);
			// 银行名称
			if (true) {
				tbSpBank.setFullName(bankCard == null ? "" : bankCard.getBankName());

				if (StringUtils.isNotBlank(tbSpBank.getFullName())) {
					tbSpBank.setFullNamePinYin(PinYinUtils.ToPinyinByBank(tbSpBank.getFullName()));
				}
			}

			// 银行卡卡种名称
			if (true) {
				tbSpBank.setTypeName(bankCard == null ? "" : bankCard.getCardTypeName());

				if (StringUtils.isNotBlank(tbSpBank.getTypeName())) {
					tbSpBank.setTypeNamePinYin(PinYinUtils.ToPinyinByBank(tbSpBank.getTypeName()));
				}
			}

			// 支行名称
			if (true) {
				tbSpBank.setBranchName(bankBranchName);
			}

			// 银行所属省份
			if (true) {
				tbSpBank.setProvince(province);
			}

			// 银行所属市
			if (true) {
				tbSpBank.setCity(city);
			}

			// // 4大银行的16位是信用卡
			// // 注意：信用卡没有开户地之说，归总行信用卡部。唯独中国银行的长城信用卡有我的地盘这个属性
			// String address = ABCBankAddr.getAddrOfBank(bankNumber.substring(6, 10));
			// tbSpBank.setProvince(address.contains("没有") ? null : address);

			HashMap<String, Object> result = Maps.newHashMap();
			result.put("bank", tbSpBank);
			result.put("bankNameList", cardService.findAllBankNameByNotRepeat());

			redis.setWithExpireTime(Constants.BANK_TINFO + userCode, tbSpBank, Constants.SINGLE_REQUEST_TIMEOUT_SECONDS);

			// cardService.saveBanks();// 银行卡列表第一次入库
			sr.setSuccess();
			sr.setResult(result);
		} else {
			sr.setResult("请提供有效的银行卡号");
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateBankOfBinding(HttpServletRequest request, ServiceResult sr, RedisUtils redis, String userCode, String bankName,
			String bankNumber, String mobile) throws Exception {
		sr.setAppFail("银行卡绑定失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("用户编码无效");
			return sr;
		}
		if (StringUtils.isBlank(bankName)) {
			sr.setResult("请选择银行卡类型");
			return sr;
		}
		if (StringUtils.isBlank(bankNumber)) {
			sr.setResult("银行卡号不能为空");
			return sr;
		}
		bankNumber = bankNumber.replaceAll(" ", "");// 清除空格
		if (!(bankNumber.length() == 16 || bankNumber.length() == 19)) {
			sr.setResult("银行卡号必须为16或19位");
			return sr;
		}
		TbSpUser user = userDao.findByUserCode(userCode);
		if (null == user) {
			sr.setResult("用户不存在");
			return sr;
		}

		// 校验银行卡信息是否被篡改
		Object obj = redis.get(Constants.BANK_TINFO + userCode);
		if (null == obj) {
			sr.setResult("请重新输入银行卡信息");
			return sr;
		}

		TbSpBank redisBank = (TbSpBank) obj;
		// 校验用户是否原用户
		if (!user.getUserCode().equals(redisBank.getUserCode())) {
			sr.setResult("参数错误[用户ID]");
			return sr;
		}
		// 校验卡号
		if (!bankNumber.equals(redisBank.getNumber())) {
			sr.setResult("请正确提交上一步信息");
			return sr;
		}

		List<TbSpBankCard> cards = cardService.findAllBank();
		for (TbSpBankCard card : cards) {
			// 用户已自行修改银行卡类型
			if (!bankName.equals(redisBank.getFullName()) && bankName.equals(card.getBankName())) {
				redisBank.setFullName(card.getBankName());
				redisBank.setFullNamePinYin(card.getBankNamePinYin());
				// 匹配当前卡种时不再继续查找
				if (card.getCardLastNo().equals(bankNumber.subSequence(0, 6))) {
					redisBank.setTypeName(card.getCardTypeName());
					redisBank.setTypeNamePinYin(card.getCardTypeNamePinYin());
					break;
				} else {
					redisBank.setTypeName("储蓄卡");
					redisBank.setTypeNamePinYin(PinYinUtils.ToPinyinByBank(redisBank.getTypeName()));
				}
			}
		}
		redis.deletelike(Constants.BANK_TINFO + userCode);// 清除当前操作使用的内容

		// 查询卡号是否被其他账户绑定
		int otherUserBanks = bankDao.findByNumberOfOtherUser(redisBank.getUserCode(), redisBank.getNumber());
		if (otherUserBanks > 0) {
			sr.setResult("该卡号已被其他账户绑定");
			return sr;
		}
		// 查询该用户所有有效的银行卡
		List<TbSpBank> banks = bankDao.findAllByUserCode(user.getUserCode(), user.getUserCodeBs());

		if (CollectionUtils.isNotEmpty(banks) && banks.size() >= 10) {
			sr.setResult("每个账户最多可绑定10张银行卡");
			return sr;
		}

		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.UP_BINDINGBANK);
		saleLog.setUserCode(userCode);
		saleLog.setRequestTime(new Date());
		saleLog.setRequestData("verifyBank:" + JSON.toJSONString(redisBank));

		// 是否存在已解绑的卡
		TbSpBank oldBank = bankDao.findByNumberOfUnbundling(redisBank.getUserCode(), redisBank.getNumber());
		if (null != oldBank) {
			// 查询是否已存在默认卡
			int isDefault = bankDao.findDefaultByUserCode(redisBank.getUserCode(), redisBank.getUserCode());
			if (isDefault < 1) {
				// 没有默认卡
				oldBank.setIsDefault(1);// 设为默认
			} else {
				// 已存在默认卡
				oldBank.setIsDefault(0);
			}
			oldBank.setMobile(mobile);
			oldBank.setUserName(user.getUserName());
			oldBank.setIdNumber(user.getIdNumber());
			oldBank.setFullName(redisBank.getFullName());// 银行名称
			oldBank.setFullNamePinYin(redisBank.getFullNamePinYin());// 银行名称全拼音
			oldBank.setTypeName(redisBank.getTypeName());// 卡类型名
			oldBank.setTypeNamePinYin(redisBank.getTypeNamePinYin());// 卡类型名全拼音
			oldBank.setBranchName(redisBank.getBranchName());// 支行名称
			oldBank.setProvince(redisBank.getProvince());// 支行所属省
			oldBank.setCity(redisBank.getCity());// 支行所属市
			oldBank.setUpdateTime(new Date());
			// 当前域名根路径+文件夹路径
			// String basePath = "https://" + request.getServerName() + "/sticsale/";
			String colorValue = ImgMainColor.getColorValue(/* basePath + */this.bankImgPathDefault, oldBank.getFullNamePinYin() + ".png");
			// 提取到主色调
			if (StringUtils.isNotBlank(colorValue)) {
				oldBank.setBackgroundColor(colorValue);
			}

			// 激活解绑的卡
			oldBank.setState(1);
			// 更新旧卡状态
			bankDao.save(oldBank);

			banks.add(oldBank);
			user.setBanks(banks);

			sr.setSuccess();
			sr.setResult(user);

			saleLog.setMark("激活解绑的银行卡");
			saleLog.setResponseData(JSON.toJSONString(oldBank));
			spSaleLogDao.save(saleLog);
			return sr;
		}

		// 创建银行卡信息
		TbSpBank newBank = new TbSpBank();
		newBank.setUserCode(redisBank.getUserCode());
		newBank.setNumber(redisBank.getNumber());
		newBank.setMobile(mobile);
		newBank.setUserName(user.getUserName());
		newBank.setIdNumber(user.getIdNumber());
		newBank.setFullName(redisBank.getFullName());// 银行名称
		newBank.setFullNamePinYin(redisBank.getFullNamePinYin());// 银行名称全拼音
		newBank.setTypeName(redisBank.getTypeName());// 卡类型名
		newBank.setTypeNamePinYin(redisBank.getTypeNamePinYin());// 卡类型名全拼音
		newBank.setBranchName(redisBank.getBranchName());// 支行名称
		newBank.setProvince(redisBank.getProvince());// 支行所属省
		newBank.setCity(redisBank.getCity());// 支行所属市
		Date nowTime = new Date();// 时间
		newBank.setCreateTime(nowTime);
		newBank.setUpdateTime(nowTime);

		// 当前域名根路径+文件夹路径
		// String basePath = "https://" + request.getServerName() + "/sticsale/";
		String colorValue = ImgMainColor.getColorValue(/* basePath + */this.bankImgPathDefault, newBank.getFullNamePinYin() + ".png");
		// 提取到主色调
		if (StringUtils.isNotBlank(colorValue)) {
			newBank.setBackgroundColor(colorValue);
		}
		if (CollectionUtils.isEmpty(banks)) {
			// 没有银行卡时设置默认银行卡信息
			newBank.setIsDefault(1);
		}

		for (TbSpBank bank : banks) {
			// 有默认银行卡时设置当前银行卡为非默认
			if (bank.getIsDefault().compareTo(1) == 0) {
				newBank.setIsDefault(0);
				break;
			}
		}
		// 创建银行卡
		bankDao.save(newBank);

		banks.add(newBank);
		user.setBanks(banks);

		sr.setSuccess();
		sr.setResult(user);

		saleLog.setMark("创建银行卡");
		saleLog.setResponseData(JSON.toJSONString(newBank));
		spSaleLogDao.save(saleLog);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateBankUnbundling(ServiceResult sr, String userCode, Integer bankId, String number) throws Exception {
		sr.setAppFail("解绑银行卡失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("用户编码无效");
			return sr;
		}
		if (bankId < 1) {
			sr.setResult("银行卡ID无效");
			return sr;
		}
		if (StringUtils.isBlank(number)) {
			sr.setResult("银行卡号不能为空");
			return sr;
		}
		if (!(number.length() == 16 || number.length() == 19)) {
			sr.setResult("银行卡号必须为16或19位");
			return sr;
		}
		TbSpUser user = userDao.findByUserCode(userCode);
		if (null == user) {
			sr.setResult("用户不存在");
			return sr;
		}
		TbSpBank bank = bankDao.findBankById(bankId);
		if (null == bank) {
			sr.setResult("银行卡不存在");
			return sr;
		}
		if (!number.equals(bank.getNumber())) {
			sr.setResult("银行卡号错误");
			return sr;
		}
		if (!user.getUserCode().equals(bank.getUserCode())) {
			sr.setResult("该银行卡不属于当前账号");
			return sr;
		}
		List<TbSpBank> banks = bankDao.findAllByUserCode(user.getUserCode(), user.getUserCodeBs());
		if (CollectionUtils.isEmpty(banks)) {
			sr.setResult("您没有绑定银行卡");
			return sr;
		}
		Date nowDate = new Date();

		TbSpSaleLog saleLog = new TbSpSaleLog();
		saleLog.setOperation(TbSpSaleLog.UP_UNBINDINGBANK);
		saleLog.setUserCode(userCode);
		saleLog.setMark("解绑银行卡");
		saleLog.setRequestTime(nowDate);
		saleLog.setRequestData("userCode:" + userCode + "bankId:" + bankId + "number:" + number);

		// 默认银行卡或者多张银行卡
		if (bank.getIsDefault().compareTo(1) == 0 && banks.size() > 1) {

			bank.setState(0);
			bank.setUpdateTime(nowDate);
			bank.setUnbundingTime(nowDate);
			bankDao.save(bank);// 解绑该卡

			// 关闭该银行卡
			if (bank.getState().compareTo(0) == 0) {
				banks.remove(bank);// 移除当前卡
			}

			TbSpBank newBank = banks.get(0);
			newBank.setIsDefault(1);
			bankDao.save(newBank);// 设置无需解绑的最新第一张卡为默认银行卡

			if (newBank.getIsDefault().compareTo(1) == 0) {
				sr.setSuccess();
				sr.setResult(banks);

				saleLog.setResponseData(JSON.toJSONString(newBank));
			}
		} else {
			// 解除非默认银行卡或者只有一张卡

			bank.setState(0);
			bank.setUpdateTime(nowDate);
			bank.setUnbundingTime(nowDate);
			bankDao.save(bank);// 解绑该卡

			// 关闭该银行卡
			if (bank.getState().compareTo(0) == 0) {
				banks.remove(bank);// 移除当前卡

				sr.setSuccess();
				sr.setResult(banks);

				saleLog.setResponseData(JSON.toJSONString(bank));
			}
		}
		spSaleLogDao.save(saleLog);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updateBankDefault(ServiceResult sr, String userCode, Integer bankId, String number) throws Exception {
		sr.setAppFail("设置默认银行卡失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("用户编码无效");
			return sr;
		}
		if (bankId < 1) {
			sr.setResult("银行卡ID无效");
			return sr;
		}
		if (StringUtils.isBlank(number)) {
			sr.setResult("银行卡号不能为空");
			return sr;
		}
		if (!(number.length() == 16 || number.length() == 19)) {
			sr.setResult("银行卡号必须为16或19位");
			return sr;
		}
		TbSpUser user = userDao.findByUserCode(userCode);
		if (null == user) {
			sr.setResult("用户不存在");
			return sr;
		}
		TbSpBank bank = bankDao.findBankById(bankId);
		if (null == bank) {
			sr.setResult("银行卡不存在");
			return sr;
		}
		if (!number.equals(bank.getNumber())) {
			sr.setResult("银行卡号错误");
			return sr;
		}
		if (!user.getUserCode().equals(bank.getUserCode())) {
			sr.setResult("该银行卡不属于当前账号");
			return sr;
		}
		if (bank.getIsDefault().compareTo(1) == 0) {
			sr.setResult("该银行卡已经是默认银行卡");
			return sr;
		}
		// 查询该用户所有有效的银行卡
		int settDefault = bankDao.updateDefaultById(new Date(), bank.getId());
		int setNotDefault = bankDao.updateNotDefaultById(new Date(), user.getUserCode(), bank.getId());
		if (settDefault > 0 || setNotDefault > 0) {
			List<TbSpBank> banks = bankDao.findAllByUserCode(user.getUserCode(), user.getUserCodeBs());
			sr.setResult(banks);
			sr.setSuccess();

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_SETDEFAULTBANK);
			saleLog.setUserCode(userCode);
			saleLog.setMark("设置默认银行卡");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("userCode:" + userCode + ",bankId：" + bankId + ",number：" + number);
			saleLog.setResponseData(JSON.toJSONString(banks));
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Override
	public ServiceResult findAllUser(String storeStartDate, String storeEndDate, String userCode, String signStartTime, String signEndTime,
			String userName, String mobile, String nickName, String branchCode, String agrementNo, String userType, Integer Maxpoints,
			Integer Minpoints, String storeFlag, Integer pageNumber, Integer pageSize) throws Exception {
		ServiceResult sr = new ServiceResult();

		List<Order> orders = new ArrayList<Order>();
		orders.add(new Order(Direction.DESC, "configSerialNo"));
		orders.add(new Order(Direction.DESC, "id"));
		Sort sort = new Sort(orders);
		String userId = Current.userId.get();
		Integer roleId = roleUserDao.findByUserid(userId).getRoleid();
		Page<TbSpUser> page = userDao.findAll(new Specification<TbSpUser>() {
			@Override
			public Predicate toPredicate(Root<TbSpUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				List<Predicate> predicate = new ArrayList<Predicate>();

				if (userCode != null) {
					// log.info(userCode);
					predicate.add(cb.like(root.get("userCode").as(String.class), "%" + userCode + "%"));
				}
				if (StringUtils.isNotEmpty(signStartTime) && StringUtils.isNotEmpty(signEndTime)) {
					predicate.add(cb.greaterThanOrEqualTo(root.get("registeDate").as(String.class), signStartTime));
					predicate.add(cb.lessThanOrEqualTo(root.get("registeDate").as(String.class), signEndTime));
				}
				if (StringUtils.isNotEmpty(storeStartDate) && StringUtils.isNotEmpty(storeEndDate)) {
					predicate.add(cb.greaterThanOrEqualTo(root.get("storeCreateTime").as(String.class), storeStartDate));
					predicate.add(cb.lessThanOrEqualTo(root.get("storeCreateTime").as(String.class), storeEndDate));
				}
				if (StringUtils.isNotEmpty(userName)) {
					log.info(userName);
					predicate.add(cb.like(root.get("userName").as(String.class), "%" + userName + "%"));
				}
				if (StringUtils.isNotEmpty(mobile)) {
					log.info(mobile);
					predicate.add(cb.like(root.get("mobile").as(String.class), "%" + mobile + "%"));
				}
				if (StringUtils.isNotEmpty(nickName)) {
					log.info(nickName);
					predicate.add(cb.like(root.get("nickName").as(String.class), "%" + nickName + "%"));
				}
				if (StringUtils.isNotEmpty(agrementNo)) {
					// log.info(agrementNo);
					predicate.add(cb.like(root.get("agrementNo").as(String.class), "%" + agrementNo + "%"));
				}
				if (StringUtils.isNotEmpty(branchCode) && !"-1".equals(branchCode)) {
					// log.info("branchCode------------" + branchCode);
					predicate.add(cb.equal(root.get("branchCode").as(String.class), branchCode));
				}
				if (StringUtils.isNotEmpty(userType) && !"-1".equals(userType)) {
					// log.info("userType------------" + userType);
					predicate.add(cb.equal(root.get("userType").as(String.class), userType));
				}
				if (null != Maxpoints) {
					// log.info("Maxpoints------------" + Maxpoints);
					predicate.add(cb.lessThanOrEqualTo(root.get("points").as(Integer.class), Maxpoints));
				}
				if (null != Minpoints) {
					// log.info("Minpoints------------" + Minpoints);
					predicate.add(cb.greaterThanOrEqualTo(root.get("points").as(Integer.class), Minpoints));
				}
				if (StringUtils.isNotEmpty(storeFlag) && !"-1".equals(storeFlag)) {
					// log.info("storeFlag------------" + storeFlag);
					predicate.add(cb.equal(root.get("storeFlag").as(String.class), storeFlag));
				}

				predicate.add(cb.equal(root.get("state").as(String.class), "1"));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();

			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort));

		List<TbSpUser> list = page.getContent();
		for (TbSpUser user : list) {
			String usercode = user.getUserCode();
			TbSpUser ref = userDao.findByUserCode(user.getRefereeId());
			if (null != ref) {
				user.setRefereeUser(ref);
			}
			List<TbSpScore> score = scoreDao.findByUserCode(usercode);
			if (CollectionUtils.isNotEmpty(score)) {
				user.setScore(score.get(0));
			}
			List<TbSpBank> bank = bankDao.findDefaultBankByUserCode(usercode, user.getUserCodeBs());
			if (CollectionUtils.isNotEmpty(bank)) {
				user.setBanks(bank);
			}
			TbSpApprove tsa = approveDao.findApproveFlow(Constants.COMMISSION_APPROVE, usercode, Constants.APPROVE_WAIT,
					Constants.FLOW_COMMISSION_RATE);
			if (null != tsa) {
				user.setApprove(tsa);
				TbSpFlowDetail flowDetail = flowDetailDao.findByNoAndNode(tsa.getFlowNo(), tsa.getFlowNode());
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getUserCode())) {// 用户审批
					String[] users = flowDetail.getUserCode().split("&");
					boolean b = Arrays.asList(users).contains(userId);
					if (b) {
						user.setApproveAuth("true");
					} else {
						user.setApproveAuth("false");
					}
				}
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getRoleCode())) {// 角色审批
					String[] roles = flowDetail.getRoleCode().split("&");
					boolean b = Arrays.asList(roles).contains(roleId.toString());
					if (b) {
						user.setApproveAuth("true");
					} else {
						user.setApproveAuth("false");
					}
				}
			}
		}
		sr.setResult(page);
		return sr;
	}

	@Override
	public ServiceResult addressList() {
		ServiceResult sr = new ServiceResult();
		List<SysServiceInfo> sysUrlInfo = iSysServiceInfoDao.findByUserName("IP_REGION");
		try {
			String address = HttpAndHttpsUtil.httpPost(sysUrlInfo.get(0).getUrl(), null, sysUrlInfo.get(0).getPassword());
			sr.setResult(address);
			String[] strArr = address.split("	");
			sr.setResCode(strArr[4]);
			sr.setSuccess();
		} catch (Exception e) {
			sr.setFail();
		}

		return sr;
	}

	@Override
	public ServiceResult updateUser(TbSpUser tbSpUser) throws Exception {
		ServiceResult sr = new ServiceResult();
		try {
			if (StringUtils.isNotBlank(tbSpUser.getNewPassword())) {
				if (tbSpUser.getNewPassword().trim().length() < 6 || tbSpUser.getNewPassword().trim().length() > 18) {
					sr.setAppFail("密码长度为6-18位");
					return sr;
				} else {
					Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
					String password = tbSpUser.getNewPassword();
					// 加密密码
					password = md5PwdEncoder.encodePassword(password);
					tbSpUser.setPassword(password);
				}
			}

			TbSpUser dnuser = userDao.findById(tbSpUser.getId()).get();

			BeanUtilExt.copybean1ToBbean2(tbSpUser, dnuser);
			dnuser.setChannelType(dnuser.getChannelType().toUpperCase());

			// dnuser.setIdNumber(tbSpUser.getIdNumber());
			// dnuser.setUserName(tbSpUser.getUserName());
			// dnuser.setBranchCode(tbSpUser.getBranchCode());
			// dnuser.setEmail(tbSpUser.getEmail());
			// dnuser.setChannelCode(tbSpUser.getChannelCode());
			// dnuser.setChannelName(tbSpUser.getChannelName());
			// dnuser.setAgrementNo(tbSpUser.getAgrementNo());
			// dnuser.setStoreFlag(tbSpUser.getStoreFlag());
			// dnuser.setState(tbSpUser.getState());
			// dnuser.setAreaCode(tbSpUser.getAreaCode());
			// dnuser.setAreaName(tbSpUser.getAreaName());
			// dnuser.setShippingAddress(tbSpUser.getShippingAddress());
			// dnuser.setUserType(tbSpUser.getUserType());
			// dnuser.setPopularity(tbSpUser.getPopularity());
			// dnuser.setTypeState(tbSpUser.getTypeState());
			// dnuser.setSaleCode(tbSpUser.getSaleCode());
			// dnuser.setSaleName(tbSpUser.getSaleName());
			//
			// dnuser.setIntroduceId(tbSpUser.getIntroduceId());
			// dnuser.setLastloginDate(dnuser.getLastloginDate());
			// dnuser.setRegisteDate(dnuser.getRegisteDate());
			// dnuser.setWxSubscribeTime(dnuser.getWxSubscribeTime());
			sr.setResult(userDao.save(dnuser));

		} catch (Exception e) {
			sr.setFail();
		}
		return sr;
	}

	@Override
	public ServiceResult findAllShopUser() {
		ServiceResult sr = new ServiceResult();
		sr.setResult(userDao.findAllShopUser());
		return sr;
	}

	@Override
	public ServiceResult shopRate(String userCode, int pageNumber, int pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.ASC, "id");
		Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
		Page<TbSpStoreConfig> plateList = storeConfigDao.findByUserCode(userCode, pageable);

		List<TbSpStoreConfig> list = plateList.getContent();
		for (TbSpStoreConfig storeConfig : list) {
			storeConfig.setProduct(productDao.findById(storeConfig.getProductId()).get());
		}
		sr.setResult(plateList);

		return sr;
	}

	@Override
	public ServiceResult agreeRate(String agreementNo, int pageNumber, int pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.ASC, "id");

		Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);

		Page<TbSpAgreementNoConfig> plateList = null;
		if (StringUtils.isNotBlank(agreementNo)) {

			log.info("----agreementNo----{}", agreementNo);

			plateList = agreementNoConfigDao.findByAgreementNo(agreementNo, pageable);
		} else {
			log.info("----findAll----");
			plateList = agreementNoConfigDao.findAll(pageable);
		}
		List<TbSpAgreementNoConfig> list = plateList.getContent();
		for (TbSpAgreementNoConfig config : list) {
			config.setProduct(productDao.findById(config.getProductId()).get());
		}
		sr.setResult(plateList);

		return sr;
	}

	@Override
	public ServiceResult deleteShopRate(Integer id, String type) {
		ServiceResult sr = new ServiceResult();
		if (null != id) {
			if ("agree".equals(type)) {
				agreementNoConfigDao.deleteById(id);
			} else if ("shop".equals(type)) {
				storeConfigDao.deleteById(id);
			}
		}
		sr.setSuccess();
		return sr;
	}

	// @Override
	// public ServiceResult setShopRate(StoreRateReq storeRate) {
	// ServiceResult sr = new ServiceResult();
	// String[] userCodeArr = storeRate.getUserCodes().split(",");
	// List<TbSpStoreConfig> stores = storeRate.getStoreConfig();
	// for (TbSpStoreConfig conf : stores) {
	// for (int i = 0; i < userCodeArr.length; i++) {
	// List<TbSpStoreConfig> dblist =
	// storeConfigDao.findByUserCodeAndProductId(userCodeArr[i],
	// conf.getProductId());
	// if (CollectionUtils.isEmpty(dblist)) {
	// TbSpStoreConfig config = new TbSpStoreConfig();
	// config.setProductId(conf.getProductId());
	// config.setRate(conf.getRate());
	// config.setUserCode(userCodeArr[i]);
	// storeConfigDao.save(config);
	// } else {
	// dblist.get(0).setRate(conf.getRate());
	// storeConfigDao.save(dblist.get(0));
	// }
	// }
	// }
	// return sr;
	// }

	@Override
	public ServiceResult setShopRate(StoreRateReq storeRate) {
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_COMMISSION_RATE);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置佣金审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置佣金审批流！");
			return sr;
		}
		if (storeRate.getUserCodes().startsWith("BS") || storeRate.getUserCodes().startsWith("WX")) {

			String[] userCodeArr = storeRate.getUserCodes().split(",");
			List<TbSpStoreConfig> stores = storeRate.getStoreConfig();
			// 校验
			for (int i = 0; i < userCodeArr.length; i++) {
				List<TbSpApprove> dbtsalist = approveDao.findConfigByTypeAndApproveId(Constants.COMMISSION_APPROVE, userCodeArr[i],
						Constants.APPROVE_WAIT, Constants.FLOW_COMMISSION_RATE);
				if (CollectionUtils.isNotEmpty(dbtsalist)) {
					sr.setFail();
					sr.setResult("请先审批" + userCodeArr[i] + "的佣金配置");
					return sr;
				}
			}
			for (int i = 0; i < userCodeArr.length; i++) {
				List<TbSpStoreConfig> list = Lists.newArrayList();
				for (TbSpStoreConfig conf : stores) {
					log.info(conf.getProductName());
					log.info(conf.getRate().toString());
					TbSpStoreConfig config = new TbSpStoreConfig();
					config.setProductId(conf.getProductId());
					config.setRate(conf.getRate());
					config.setUserCode(userCodeArr[i]);
					config.setProductName(conf.getProductName());
					config.setAddDate(new Date());
					String productEname = productDao.findById(conf.getProductId()).get().getProductEname();

					config.setProductEname(StringUtils.isNotBlank(productEname) ? productEname : "");
					list.add(config);
				}
				String jsonstring = JSONObject.toJSONString(list, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
				log.info(jsonstring);
				TbSpApprove tsa = new TbSpApprove();
				tsa.setStatus(Constants.APPROVE_WAIT);
				tsa.setApproveId(userCodeArr[i]);
				tsa.setContent(jsonstring);
				// tsa.setOriginalStatus(status);
				tsa.setApplyTime(new Date());
				tsa.setFlowNo(flow.getFlowNo());
				tsa.setFlowType(Constants.FLOW_COMMISSION_RATE);
				tsa.setFlowNode(flow.getLastFlowNode());
				tsa.setApplyUser(Current.userInfo.get().getUserId());
				tsa.setType(Constants.COMMISSION_APPROVE);
				approveDao.save(tsa);
				// 审批排序
				userDao.updateConfigSerialNo(userCodeArr[i], 1);
			}
		} else {// 业务关系代码佣金配置

			List<TbSpStoreConfig> stores = storeRate.getStoreConfig();
			// 校验
			List<TbSpApprove> dbtsalist = approveDao.findConfigByTypeAndApproveId(Constants.AGREEMENT_COMMISSION_APPROVE, storeRate.getUserCodes(),
					Constants.APPROVE_WAIT);
			if (CollectionUtils.isNotEmpty(dbtsalist)) {
				sr.setFail();
				sr.setResult("请先审批" + storeRate.getUserCodes() + "的佣金配置");
				return sr;
			}

			TQueryLmAgentResponseDto dto = shopService.findAgreementNo(storeRate.getUserCodes());
			if (CollectionUtils.isEmpty(dto.getPrpLmAgentList())) {
				sr.setFail();
				sr.setResult("无效的业务关系代码！");
				return sr;
			}
			List<TbSpAgreementNoConfig> list = Lists.newArrayList();
			for (TbSpStoreConfig conf : stores) {
				log.info(conf.getProductName());
				log.info(conf.getRate().toString());
				TbSpAgreementNoConfig config = new TbSpAgreementNoConfig();
				config.setProductId(conf.getProductId());
				config.setRate(conf.getRate());
				config.setAgreementNo(storeRate.getUserCodes());
				config.setProductName(conf.getProductName());
				config.setAddDate(new Date());
				String productEname = productDao.findById(conf.getProductId()).get().getProductEname();

				config.setProductEname(StringUtils.isNotBlank(productEname) ? productEname : "");
				list.add(config);
			}
			String jsonstring = JSONObject.toJSONString(list, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
			log.info(jsonstring);
			TbSpApprove tsa = new TbSpApprove();
			tsa.setStatus(Constants.APPROVE_WAIT);
			tsa.setApproveId(storeRate.getUserCodes());
			tsa.setContent(jsonstring);
			// tsa.setOriginalStatus(status);
			tsa.setApplyTime(new Date());
			tsa.setFlowNo(flow.getFlowNo());
			tsa.setFlowType(Constants.FLOW_COMMISSION_RATE);
			tsa.setFlowNode(flow.getLastFlowNode());
			tsa.setApplyUser(Current.userInfo.get().getUserId());
			tsa.setType(Constants.AGREEMENT_COMMISSION_APPROVE);
			approveDao.save(tsa);

		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Modifying(clearAutomatically = true) // @Modifying注解需要使用clearAutomatically=true，同一接口更新后立即查询获得更新后的数据,默认false查询还是更新前的数据
	@Override
	public ServiceResult updatePwdByUserCode(ServiceResult sr, String userCode, String password) throws Exception {
		sr.setAppFail("密码修改失败");

		if (StringUtils.isBlank(userCode)) {
			sr.setResult("编码无效");
			return sr;
		}
		TbSpUser tbSpUser = userDao.findByUserCode(userCode);
		if (tbSpUser == null) {
			sr.setResult("用户不存在");
			return sr;
		}
		if (StringUtils.isBlank(password)) {
			password = "";
		} else {
			if (password.trim().length() < 10 || password.trim().length() > 50) {
				sr.setResult("密码长度为10-50位");
				return sr;
			}

			// 校验原密码
			if (password.equals(tbSpUser.getPassword())) {
				sr.setResult("新密码不能和原密码相同");
				return sr;
			}
		}
		// 修改
		int updateNo = userDao.updatePwdByUserCode(password, userCode);
		if (updateNo == 1) {
			sr.setResult("密码修改成功");
			sr.setSuccess();

			TbSpSaleLog saleLog = new TbSpSaleLog();
			saleLog.setOperation(TbSpSaleLog.UP_SETDEFAULTBANK);
			saleLog.setUserCode(userCode);
			saleLog.setMark("系统账户  - 修改客户[" + userCode + "]密码");
			saleLog.setRequestTime(new Date());
			saleLog.setRequestData("userCode:" + userCode + ",password：" + password);
			saleLog.setResponseData(JSON.toJSONString(tbSpUser));
			spSaleLogDao.save(saleLog);
		}
		return sr;
	}

	@Override
	public ServiceResult addUser(TbSpUser tbSpUser) {
		ServiceResult sr = new ServiceResult();
		Timestamp timestamp = new Timestamp(new Date().getTime());
		if (StringUtils.isNotBlank(tbSpUser.getNewPassword())) {
			if (tbSpUser.getNewPassword().trim().length() < 6 || tbSpUser.getNewPassword().trim().length() > 18) {
				sr.setAppFail("密码长度为6-18位");
				return sr;
			} else {
				Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
				String password = tbSpUser.getNewPassword();
				// 加密密码
				password = md5PwdEncoder.encodePassword(password);
				tbSpUser.setPassword(password);
			}
		}
		if (StringUtils.isBlank(tbSpUser.getState())) {
			tbSpUser.setState(Constants.TRUE);
		}
		if (StringUtils.isBlank(tbSpUser.getLoginState())) {
			tbSpUser.setLoginState(Constants.TRUE);// 已登录
		}
		if (StringUtils.isBlank(tbSpUser.getUserType())) {
			tbSpUser.setUserType("2");// 用户类型
		}
		if (tbSpUser.getLoginTimes() == 0) {
			tbSpUser.setLoginTimes(0);
		}
		if (tbSpUser.getLoginTimesContinuity() == 0) {
			tbSpUser.setLoginTimesContinuity(0);
		}
		if (StringUtils.isBlank(tbSpUser.getHeadUrl())) {
			tbSpUser.setHeadUrl(this.userHeadImgPathDefault + this.headImgDefault);
		}
		if (StringUtils.isBlank(tbSpUser.getIdType())) {
			tbSpUser.setIdType(Constants.TRUE);
		}
		if (StringUtils.isBlank(tbSpUser.getTypeState())) {
			tbSpUser.setTypeState("11");// 1:成交量 2:人气 1显示:0不显示
		}
		tbSpUser.setRegisteDate(timestamp);// 注册时间
		tbSpUser.setLastloginDate(timestamp);// 最后登录时间
		if (StringUtils.isNotBlank(tbSpUser.getStoreFlag()) && Constants.TRUE.equals(tbSpUser.getStoreFlag())) {
			tbSpUser.setStoreCreateTime(timestamp);
		}
		if (StringUtils.isBlank(tbSpUser.getHeadUrl())) {
			tbSpUser.setHeadUrl(this.userHeadImgPathDefault + this.headImgDefault);
		}
		// 普通注册
		tbSpUser.setUserCode(iSequenceService.getUserCodeSequence("BS"));
		tbSpUser.setUserCodeBs(null);

		sr.setResult(userDao.save(tbSpUser));
		return sr;
	}

	@Override
	public String getTopUserCode(String userCode) {

		if (StringUtils.isEmpty(userCode)) {
			return "";
		} else {
			while (true) {
				List<TbSpUser> userList = userDao.findUserCodeBs(userCode);
				if (CollectionUtils.isEmpty(userList)) {
					return userCode;
				} else {
					userCode = userList.get(0).getUserCode();
				}
			}
		}

	}
}
